﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Nova.Parsing.GoldParser.Semantic;
using Nova.Parsing.Tokens;

namespace Nova.Parsing.Constructs
{
    public abstract class ExpressionConstruct : NovaConstruct
    {
    }

    public sealed class NullExpression : ExpressionConstruct
    {
        [Rule(@"<For-Loop Exp Cond> ::= ")]
        public NullExpression()
        {
        }
    }

    public sealed class NormalExpression : ExpressionConstruct
    {
        private ExpressionConstruct m_LeftExpression;
        private ExpressionConstruct m_RightExpression;
        private OperatorType m_Operator;

        [Rule(@"<Or Exp> ::= <Or Exp> '||' <And Exp>")]
        [Rule(@"<And Exp> ::= <And Exp> '&&' <Bitwise Or Exp>")]
        [Rule(@"<Bitwise Or Exp> ::= <Bitwise Or Exp> '|' <Bitwise Xor Exp>")]
        [Rule(@"<Bitwise Xor Exp> ::= <Bitwise Xor Exp> '^' <Bitwise And Exp>")]
        [Rule(@"<Bitwise And Exp> ::= <Bitwise And Exp> '&' <Equality Exp>")]
        [Rule(@"<Equality Exp> ::= <Equality Exp> '==' <Compare Exp>")]
        [Rule(@"<Equality Exp> ::= <Equality Exp> '!=' <Compare Exp>")]
        [Rule(@"<Compare Exp> ::= <Compare Exp> '<' <Shift Exp>")]
        [Rule(@"<Compare Exp> ::= <Compare Exp> '<=' <Shift Exp>")]
        [Rule(@"<Compare Exp> ::= <Compare Exp> '>' <Shift Exp>")]
        [Rule(@"<Compare Exp> ::= <Compare Exp> '>=' <Shift Exp>")]
        [Rule(@"<Shift Exp> ::= <Shift Exp> '<<' <Add Exp>")]
        [Rule(@"<Shift Exp> ::= <Shift Exp> '<<<' <Add Exp>")]
        [Rule(@"<Shift Exp> ::= <Shift Exp> '>>' <Add Exp>")]
        [Rule(@"<Shift Exp> ::= <Shift Exp> '>>>' <Add Exp>")]
        [Rule(@"<Add Exp> ::= <Add Exp> '+' <Mult Exp>")]
        [Rule(@"<Add Exp> ::= <Add Exp> '-' <Mult Exp>")]
        [Rule(@"<Mult Exp> ::= <Mult Exp> '*' <Unary Exp>")]
        [Rule(@"<Mult Exp> ::= <Mult Exp> '/' <Unary Exp>")]
        [Rule(@"<Mult Exp> ::= <Mult Exp> '%' <Unary Exp>")]
        public NormalExpression(ExpressionConstruct leftExp, OperatorToken op, ExpressionConstruct rightExp)
        {
            m_LeftExpression = leftExp;
            m_Operator = op.Operator;
            m_RightExpression = rightExp;
        }

        public ExpressionConstruct LeftExpression
        {
            get { return m_LeftExpression; }
        }

        public ExpressionConstruct RightExpression
        {
            get { return m_RightExpression; }
        }

        public OperatorType Operator
        {
            get { return m_Operator; }
        }
    }

    public sealed class UnaryExpression : ExpressionConstruct
    {
        private OperatorType m_Operator;
        private ValueConstruct m_Value;

        [Rule(@"<Unary Exp> ::= '-' <Value>")]
        [Rule(@"<Unary Exp> ::= '+' <Value>")]
        [Rule(@"<Unary Exp> ::= '!' <Value>")]
        [Rule(@"<Unary Exp> ::= '~' <Value>")]
        [Rule(@"<Unary Exp> ::= '--' <Value>")]
        [Rule(@"<Unary Exp> ::= '++' <Value>")]
        public UnaryExpression(OperatorToken op, ValueConstruct value)
        {
            if (op.Operator != OperatorType.Add ||
                op.Operator != OperatorType.Subtract ||
                op.Operator != OperatorType.BoolNot ||
                op.Operator != OperatorType.BitwiseNot ||
                op.Operator != OperatorType.UnaryAdd ||
                op.Operator != OperatorType.UnarySubtract)
            {
                throw new ArgumentException("Invalid unary operator: " + op.Operator.ToString());
            }

            m_Value = value;
            m_Operator = op.Operator;
        }

        public OperatorType Operator
        {
            get { return m_Operator; }
            set { m_Operator = value; }
        }

        public ValueConstruct Value
        {
            get { return m_Value; }
            set { m_Value = value; }
        }
    }

    public sealed class RightUnaryExpression : ExpressionConstruct
    {
        private OperatorType m_Operator;
        private ValueConstruct m_Value;

        [Rule(@"<Sub Expression> ::= <Value> '--'")]
        [Rule(@"<Sub Expression> ::= <Value> '++'")]
        public RightUnaryExpression(ValueConstruct value, OperatorToken op)
        {
            if (op.Operator != OperatorType.UnaryAdd || op.Operator != OperatorType.UnarySubtract)
            {
                throw new ArgumentException("Invalid unary operator: " + op.Operator.ToString());
            }

            m_Operator = op.Operator;
            m_Value = value;
        }

        public OperatorType Operator
        {
            get { return m_Operator; }
            set { m_Operator = value; }
        }

        public ValueConstruct Value
        {
            get { return m_Value; }
            set { m_Value = value; }
        }
    }

    public sealed class SingleValueExpression : ExpressionConstruct
    {
        private ValueConstruct m_Value;

        [Rule(@"<Sub Expression> ::= <Value>")]
        public SingleValueExpression(ValueConstruct value)
        {
            m_Value = value;
        }

        public ValueConstruct Value
        {
            get { return m_Value; }
        }
    }

    public sealed class FunctionExpression : ExpressionConstruct
    {
        private FunctionStatement m_Function;

        [Rule(@"<Sub Expression> ::= Identifier '(' <Argument List Opt> ')'")]
        public FunctionExpression(Identifier funcName, IgnoredToken iA, ArgumentSetConstruction args, IgnoredToken iB)
        {
            m_Function = new FunctionStatement(funcName, null, args, null, null);
        }

        public FunctionStatement Function
        {
            get { return m_Function; }
        }
    }
}
